import {lobby} from "../lobby";
import {RestReply} from "db://assets/proto/shared/v1/msgs";
import {BinaryReader} from "@bufbuild/protobuf/dist/cjs/wire";

type HttpType = 'OPTIONS' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'DELETE' | 'TRACE' | 'CONNECT'
/**
 * 网络请求
 */
export default class HttpClient {
    // public static host: string = "http://118.25.168.135:8090/api/";//'http://118.89.123.3:8080';//116.62.119.201:3000;https://dingdang.haidiao888.com
    // public static host: string = "http://192.168.10.103:8002/api/";//'http://118.89.123.3:8080';//116.62.119.201:3000;https://dingdang.haidiao888.com
    public static host: string = "http://127.0.0.1:8002/api/";//'http://118.89.123.3:8080';//116.62.119.201:3000;https://dingdang.haidiao888.com
    private static instance: HttpClient = null!;
    private encoder: TextEncoder = new TextEncoder();
    private static uid: number = 0;
    private static token: string = null!;

    private constructor() {
    }

    public static getInstance(): HttpClient {
        if (!this.instance) {
            this.instance = new HttpClient();
        }
        return this.instance;
    }

    public setToken(token: string) {
        HttpClient.token = token;
    }

    public setUid(uid: number) {
        HttpClient.uid = uid;
    }

    requestAsync<U>(
        type: HttpType,
        uri: string,
        ResponseType: { decode: (input: Uint8Array | BinaryReader, length?: number) => U },
        param?: Uint8Array,
        pathArg: string | number | null = null!,
    ) {
        return new Promise<U>((rs, rj) => {
            let callback = (res: U) => {
                console.log('resp callback', res);
                rs(res)
            }
            let errorCb = (res: RestReply) => {
                rj(res)
            }
            this.request(type, uri, ResponseType, pathArg, param, callback, errorCb)
        })
    }

    /**
     * @param type method
     * @param uri path
     * @param ResponseType 返回值类型
     * @param param data
     * @param pathArg 路径参数
     * @param cb callback
     * @param errorCb errorCallback
     */
    public request<U>(
        type: HttpType,
        uri: string,
        ResponseType: { decode: (input: Uint8Array | BinaryReader, length?: number) => U },
        pathArg: string | number | null = null!,
        param?: Uint8Array,
        cb?: (data: U) => void,
        errorCb?: (res: RestReply) => void,
    ) {
        let requestURL = HttpClient.host + uri + (pathArg ? `/${pathArg}` : '');
        let xhr = new XMLHttpRequest();
        xhr.responseType = 'arraybuffer'
        xhr.timeout = 5000;
        xhr.open(type, requestURL, true);
        if (HttpClient.uid) {
            xhr.setRequestHeader("uid", HttpClient.uid.toString());
        }
        if (HttpClient.token) {
            xhr.setRequestHeader("world-access-token", HttpClient.token);
        }
        if (type != "GET") {
            xhr.setRequestHeader('Content-Type', 'application/proto');
        }

        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                let res = new Uint8Array(xhr.response as ArrayBuffer);
                try {
                    const restReply = RestReply.decode(res!);
                    if (xhr.status >= 200 && xhr.status < 300) {
                        if (restReply.code == 0) {
                            if (cb) {
                                if (restReply.data) {
                                    const data = restReply.data!
                                    cb(ResponseType.decode(data.value))
                                }
                            }
                        } else {
                            if (errorCb) errorCb(restReply)
                            lobby.instance?.showToast(restReply.message);
                        }
                    } else {
                        if (errorCb) errorCb(restReply)
                        else lobby.instance?.showToast("请求失败");
                    }
                } catch (e) {
                    console.error(e);
                    if (errorCb) {
                        // errorCb()
                    }
                }


            }
        };
        switch (type) {
            case "GET":
                xhr.send();
                break;
            case "POST":
                xhr.send(param);
                break;
            default:
                xhr.send(param);
                break;
        }
    }

}

export const http: HttpClient = HttpClient.getInstance();